package com.health.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.health.system.common.exception.TreeDeleteException;
import com.health.system.common.utils.UserAuthUtil;
import com.health.system.dto.MenuTreeListDTO;
import com.health.system.entity.Menu;
import com.health.system.mapper.MenuMapper;
import com.health.system.mapper.RoleMapper;
import com.health.system.service.MenuService;
import com.health.system.vo.MenuTreeListSearchVo;
import com.health.system.vo.UpdateStatusVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private RoleMapper roleMapper;

    @Transactional
    @Override
    public void deleteById(Long id) {
        int size = menuMapper.selectList(new LambdaQueryWrapper<Menu>().eq(Menu::getParentId, id)).size();
        if (size > 0) {
            throw new TreeDeleteException();
        }

        menuMapper.deleteById(id);
        roleMapper.deleteRelationMenu(id);
    }

    @Override
    public void updateStatus(UpdateStatusVo vo) {
        Menu menu = Menu.builder()
                .id(vo.getId())
                .isHidden(vo.getStatus())
                .build();
        menuMapper.updateById(menu);
    }

    @Override
    public List<MenuTreeListDTO> treeList(MenuTreeListSearchVo vo) {
        List<Menu> result = menuMapper.selectList(new LambdaQueryWrapper<Menu>()
                .like(StringUtils.isNotBlank(vo.getKeyword()), Menu::getName, vo.getKeyword()));

        return result.stream()
                .filter(p -> p.getParentId() == 0)
                .map(m -> MenuTreeListDTO.builder()
                        .id(m.getId())
                        .name(m.getName())
                        .icon(m.getIcon())
                        .orderNum(m.getOrderNum())
                        .path(m.getPath())
                        .component(m.getComponent())
                        .hidden(m.getIsHidden())
                        .children(getChildren(m.getId(), result))
                        .build())
                .sorted(Comparator.comparing(MenuTreeListDTO::getOrderNum))
                .collect(Collectors.toList());
    }

    @Override
    public List<MenuTreeListDTO> menuByUser() {
        List<Menu> result = menuMapper.treeByUserId(UserAuthUtil.authId());

        return result.stream()
                .filter(p -> p.getParentId() == 0)
                .map(m -> MenuTreeListDTO.builder()
                        .id(m.getId())
                        .name(m.getName())
                        .icon(m.getIcon())
                        .path(m.getPath())
                        .orderNum(m.getOrderNum())
                        .children(getChildren(m.getId(), result))
                        .build())
                .sorted(Comparator.comparing(MenuTreeListDTO::getOrderNum))
                .collect(Collectors.toList());
    }

    private List<MenuTreeListDTO> getChildren(Long id, List<Menu> data) {
        return data.stream()
                .filter(c -> c.getParentId().equals(id))
                .map(m -> MenuTreeListDTO.builder()
                        .id(m.getId())
                        .name(m.getName())
                        .icon(m.getIcon())
                        .orderNum(m.getOrderNum())
                        .path(m.getPath())
                        .component(m.getComponent())
                        .hidden(m.getIsHidden())
                        .children(getChildren(m.getId(), data))
                        .orderNum(m.getOrderNum())
                        .build())
                .sorted(Comparator.comparing(MenuTreeListDTO::getOrderNum))
                .collect(Collectors.toList());
    }

}
